﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PServiceBus.Core.Interface;
using PServiceBus.Core.Runtime.Configuration;
using PServiceBus.Core.Runtime.Topics;
using System.Collections;
using System.Collections.Concurrent;

namespace PServiceBus.Core.Manager {
    public class TopicManager : IEnumerable<ITopic> {
        private IObjectManager<ITopic> _topics;
        private string _address, _addressID;
        private ConcurrentDictionary<string, ITopic> _cachedTopics = new ConcurrentDictionary<string, ITopic>();
        private ConcurrentDictionary<Guid, string> _cachedTopicIDs = new ConcurrentDictionary<Guid, string>();

        private static TopicManager _current = null;
        public static TopicManager Current {
            get {
                if (_current == null) _current = new TopicManager();
                return _current;
            }
        }

        private IObjectManager<ITopic> Topics {
            get {
                if (_topics == null)
                    _topics = ObjectManager<ITopic>.Create(_address, _addressID);
                return _topics;
            }
        }

        public void Init(string address, string addressID) {
            _address = address;
            _addressID = addressID;
        }

        public void Attach(ITopic topic) {
            Topics.Attach(topic);
            _cachedTopics[topic.Name] = topic;
            _cachedTopicIDs[topic.ID] = topic.Name;
        }
        public void AttachMany(IEnumerable<ITopic> topics) {
            Topics.AttachMany(topics);
            foreach (var topic in topics) {
                _cachedTopics[topic.Name] = topic;
                _cachedTopicIDs[topic.ID] = topic.Name;
            }
        }
        public void Detach(ITopic topic) {
            Topics.Detach(topic);
            string key = string.Empty;
            _cachedTopics.TryRemove(topic.Name, out topic);
            _cachedTopicIDs.TryRemove(topic.ID, out key);
        }
        public void DetachMany(IEnumerable<ITopic> topics) {
            Topics.DetachMany(topics);
            string key = string.Empty;
            var tp = default(ITopic);
            foreach (var topic in topics) {
                _cachedTopics.TryRemove(topic.Name, out tp);
                _cachedTopicIDs.TryRemove(topic.ID, out key);
            }
        }
        public ITopic GetTopic(Guid id) {
            string key = string.Empty;
            if (_cachedTopicIDs.TryGetValue(id, out key)) 
                return _cachedTopics[key];
            var topic = Topics.Get(id);
            if (topic != null) {
                _cachedTopics[topic.Name] = topic;
                _cachedTopicIDs[topic.ID] = topic.Name;
            }
            return topic;
        }

        public ITopic GetTopic(string name) {
            var tp = default(ITopic);
            if (_cachedTopics.TryGetValue(name, out tp))
                return tp;
            tp = Topics.FirstOrDefault(topic => topic.Name == name);
            if (tp != null) {
                _cachedTopics[tp.Name] = tp;
                _cachedTopicIDs[tp.ID] = tp.Name;
            }
            return tp;
        }

        #region IEnumerable<ITopic> Members

        public IEnumerator<ITopic> GetEnumerator() {
            return Topics.GetEnumerator();
        }

        #endregion

        #region IEnumerable Members

        IEnumerator IEnumerable.GetEnumerator() {
            return GetEnumerator();
        }

        #endregion
    }
}
